package ink.mint.neural;

import ink.mint.activation.ActivationType;
import ink.mint.loss.LossType;
import ink.mint.parameter.Parameter;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

public class MultiLayerConfiguration {

    /**
     * 数据集Xi转换的矩阵 图片
     */
    private double[][] X;
    /**
     * 数据集Yi转换的向量 标签
     */
    private double[] Y;
    /**
     * 神经网络
     */
    private NeuralNetwork neuralNetwork;
    /**
     * 参数
     */
    private Parameter parameter;

    /**
     * 多层感知器网络配置构造函数
     *
     * @param X Xi转换的矩阵 图片
     * @param Y Yi转换的向量 标签
     */
    public MultiLayerConfiguration(double[][] X, double[] Y) {
        this.X = X;
        this.Y = Y;
        this.neuralNetwork = new NeuralNetwork();
        this.neuralNetwork.setX(X).setY(Y);

    }

    /**
     * 多层感知器网络保存参数函数
     *
     * @param ParameterFullFileNamePath 参数保存全路径名（相对路径）
     * @return 多层感知器网络配置
     */
    public MultiLayerConfiguration saveParameter(String ParameterFullFileNamePath) {
        this.parameter = new Parameter(ParameterFullFileNamePath);
        return this;
    }

    /**
     * 多层感知器网络读取参数函数
     *
     * @param ParameterFullFileNamePath 参数读取全路径名（相对路径）
     * @return 多层感知器网络配置
     * @throws IOException            文件未找到异常
     * @throws ClassNotFoundException 反序列化类未找到异常
     */
    public MultiLayerConfiguration readParameter(String ParameterFullFileNamePath) throws IOException, ClassNotFoundException {
        this.parameter = new Parameter(ParameterFullFileNamePath);
        List<Layer> layerList = parameter.deSerialize();
        this.neuralNetwork.setLayerList(layerList);
        return this;
    }

    /**
     * 多层感知器网络层配置函数
     *
     * @param layer 网络层
     * @return 多层感知器网络配置
     */
    public MultiLayerConfiguration layerConfiguration(Layer layer) {
        neuralNetwork.addLayer(layer);
        return this;
    }

    /**
     * 多层感知器损失配置函数
     *
     * @param lossType 损失函数类型
     * @return 多层感知器网络配置
     */
    public MultiLayerConfiguration lossConfiguration(LossType lossType) {
        neuralNetwork.setLoss(lossType);
        return this;
    }

    /**
     * 多层感知器学习率配置函数
     *
     * @param learningRate 学习率
     * @return 多层感知器网络配置
     */
    public MultiLayerConfiguration learningRateConfiguration(double learningRate) {
        neuralNetwork.setLearningRate(learningRate);
        return this;
    }

    /**
     * 多层感知器训练函数
     *
     * @return 多层感知器网络配置
     */
    public MultiLayerConfiguration train() {
        neuralNetwork.train();
        parameter.serialize(neuralNetwork.getLayerList());
        return this;
    }

    /**
     * 多层感知器运行函数
     *
     * @return 多层感知器网络配置
     */
    public MultiLayerConfiguration run() {
        neuralNetwork.run();
        return this;
    }

    /**
     * 获取数据集Xi转换的矩阵 图片
     *
     * @return 数据集Xi转换的矩阵 图片
     */
    public double[][] getX() {
        return X;
    }

    /**
     * 设置数据集Xi转换的矩阵 图片
     *
     * @param x 数据集Xi转换的矩阵 图片
     */
    public void setX(double[][] x) {
        X = x;
    }

    /**
     * 获取数据集Yi转换的向量 标签
     *
     * @return 数据集Yi转换的向量 标签
     */
    public double[] getY() {
        return Y;
    }

    /**
     * 设置数据集Yi转换的向量 标签
     *
     * @param Y 数据集Yi转换的向量 标签
     */
    public void setY(double[] Y) {
        Y = Y;
    }

    /**
     * 获取神经网络
     *
     * @return 神经网络
     */
    public NeuralNetwork getNeuralNetwork() {
        return neuralNetwork;
    }

    /**
     * 设置神经网络
     *
     * @param neuralNetwork 神经网络
     */
    public void setNeuralNetwork(NeuralNetwork neuralNetwork) {
        this.neuralNetwork = neuralNetwork;
    }

    /**
     * 获取参数
     *
     * @return 参数
     */
    public Parameter getParameter() {
        return parameter;
    }

    /**
     * 设置参数
     *
     * @param parameter 参数
     */
    public void setParameter(Parameter parameter) {
        this.parameter = parameter;
    }
}
